﻿using LowCoding.Common.Security;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Security.Claims;
using System.Text;

namespace LowCoding.Common.JWT
{
    public class JwtTokenHelper
    {
        /// <summary>
        /// 加密方法
        /// </summary>
        /// <param name="username"></param>
        /// <param name="_tokenOptions"></param>
        /// <returns></returns>

        public TokenResult AuthorizeToken(LoginUserDto user, JWTTokenOptions _tokenOptions)
        {
            //基于声明的认证
            var claims = new[]
            {
                new Claim(ClaimTypes.UserId,user.UserId.ToString()),
                new Claim(ClaimTypes.UsrName,user.UsrName.ToString()),

                new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString())//jwt的唯一标识
            };
            //秘钥 转化成UTF8编码的字节数组
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenOptions.Secret));
            //资格证书 秘钥加密
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var jwtToken = new JwtSecurityToken(_tokenOptions.Issuer, _tokenOptions.Audience, claims,//发起人 订阅者
            expires: DateTime.Now.AddSeconds(_tokenOptions.Expires),//过期时间
            signingCredentials: credentials);//秘钥

            var securityToken = new JwtSecurityTokenHandler().WriteToken(jwtToken);//序列化jwt格式

            //生成令牌字符串
            return new TokenResult()
            {
                Access_token = "Bearer " + securityToken,
                //Access_token = securityToken,
                Expires_in = _tokenOptions.Expires
            };
        }
        /// <summary>
        /// 解密
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="token"></param>
        /// <returns></returns>
        public static T GetUserDto<T>(string token) where T : class
        {
            string key = AppSettings.JwtSecretKey;//秘钥
                                                  //解密方法
            JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
            TokenValidationParameters varParam = new TokenValidationParameters();
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
            varParam.IssuerSigningKey = securityKey;
            varParam.ValidateIssuer = false;
            varParam.ValidateAudience = false;
            ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(token, varParam, out SecurityToken secToken);
            //输出结果
            var user = claimsPrincipal.Claims;
            Type type = typeof(T);

            //  创建一个类T的实例
            object entity = type.Assembly.CreateInstance(type.FullName);

            // 得到类T的名称(不包含命名空间)
            string name = type.Name;

            // 获取类T的所有属性
            PropertyInfo[] props = type.GetProperties();

            // 遍历类T的属性赋值
            foreach (PropertyInfo prop in props)
            {
                if (prop.Name == ClaimTypes.UserId)
                {
                    prop.SetValue(entity, user?.Where(s => s.Type.Contains(ClaimTypes.UserId))?.FirstOrDefault().Value);
                }
                if (prop.Name == ClaimTypes.UsrName)
                {
                    prop.SetValue(entity, user?.Where(s => s.Type.Contains(ClaimTypes.UsrName))?.FirstOrDefault().Value);
                }
            }
            return (T)entity;
        }
    }
}
